#ifndef CVX_XFORM_H
#define CVX_XFORM_H 1


#include "cvxImage.h"
#include "cvxImgfeatures.h"
#include <math.h>

struct CvxFeature;

/** holds feature data relevant to ransac */
struct CvxRansacData
{
	void* orig_feat_data;
	int sampled;
};

/** pessimistic estimate of fraction of inlers for RANSAC */
#define CVX_RANSAC_INLIER_FRAC_EST 0.25

/** estimate of the probability that a correspondence supports a bad model */
//?
#define CVX_RANSAC_PROB_BAD_SUPP 0.10

/**
Prototype for transformation functions passed to ransac_xform().  Functions
of this type should compute a transformation matrix given a set of point
correspondences.

@param pts array of points
@param mpts array of corresponding points; each \a pts[\a i], \a i=0..\a n-1,
corresponds to \a mpts[\a i]
@param n number of points in both \a pts and \a mpts

@return Should return a transformation matrix that transforms each point in
\a pts to the corresponding point in \a mpts or NULL on failure.
*/
typedef CvMat* (*ransacXformFn)( CvPoint2D64f* pts, CvPoint2D64f* mpts,
								  int n );

/**
Prototype for error functions passed to ransac_xform().  For a given
point, its correspondence, and a transform, functions of this type should
compute a measure of error between the correspondence and the point after
the point has been transformed by the transform.

@param pt a point
@param mpt \a pt's correspondence
@param T a transform

@return Should return a measure of error between \a mpt and \a pt after
\a pt has been transformed by the transform \a T.
*/
typedef double (*ransacRrrFn)( CvPoint2D64f pt, CvPoint2D64f mpt, CvMat* M );


class CvxXform
{
public:
	static CvMat* ransacXform( CvxFeature* features, int n, int mtype,
							   ransacXformFn xform_fn, int m, double p_badxform,
							   ransacRrrFn err_fn, double err_tol,
						CvxFeature*** inliers, int* n_in );
	static CvMat* lsqHomog( CvPoint2D64f* pts, CvPoint2D64f* mpts, int n );
	static double homogXferErr( CvPoint2D64f pt, CvPoint2D64f mpt, CvMat* H );

private:
	static int getMatchedFeatures( CvxFeature* features, int n, int mtype,
									 CvxFeature*** matched );
	static CvxFeature* getMatch( CvxFeature* feat, int mtype );
	static double distSq2D( CvPoint2D64f p1, CvPoint2D64f p2 );
	static CvPoint2D64f perspXformPt( CvPoint2D64f pt, CvMat* T );
	static int calcMinInliers( int n, int m, double p_badsupp, double p_badxform );
	static CvxFeature** drawRansacSample( CvxFeature** features, int n, int m );
	static void extractCorrespPts( CvxFeature** features, int n, int mtype,
								   CvPoint2D64f** pts, CvPoint2D64f** mpts );
	static int findConsensus( CvxFeature** features, int n, int mtype,
							  CvMat* M, ransacRrrFn err_fn, double err_tol,
							  CvxFeature*** consensus );


	//inline
	static inline double logFactorial( int n )
	{
		//Returns log( n! )
		double f = 0;
		int i;
		for( i = 1; i <= n; i++ )
			f += log( (double)i );
		return f;
	}
	static inline CvxRansacData* featRansacData( CvxFeature *feat )
	{
		return (CvxRansacData*) (feat->feature_data );
	}
	static inline void releaseMem( CvPoint2D64f* pts1, CvPoint2D64f* pts2,
								   CvxFeature** features )
	{
		free( pts1 );
		free( pts2 );
		if( features )
			free( features );
	}
		

	
};
#endif